package com.mengxuegu.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mengxuegu.member.base.Page;
import com.mengxuegu.member.base.Result;
import com.mengxuegu.member.entity.Staff;
import com.mengxuegu.member.mapper.StaffMapper;
import com.mengxuegu.member.req.PasswordREQ;
import com.mengxuegu.member.req.StaffREQ;
import com.mengxuegu.member.service.IStaffService;
import com.mengxuegu.member.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 十一捉一
 * @since 2020-12-01
 */
@Service
public class StaffServiceImpl extends ServiceImpl<StaffMapper, Staff> implements IStaffService {

    @Override
    public Result search(long page, long size, StaffREQ req) {
        QueryWrapper query = new QueryWrapper();
        if(req != null) {
            if(StringUtils.isNotBlank(req.getName())) {
                query.like("name", req.getName());
            }
            if(StringUtils.isNotBlank(req.getUsername())) {
                query.like("username", req.getUsername());
            }
        }

        // TODO 啊这
//        就算加密了，也不能随便把密码返回过去吧。。我来加个设密码为空。
//        注意这里用Page接收，不然无法调用getRows()方法，而调用getRecords()的话因为我们重写了方法导致会是空列表。
        Page<Staff> data = baseMapper.selectPage(new Page<Staff>(page, size), query);
        List<Staff> staffList = new ArrayList<>();
//        如上所述，这里用getRows()
        for (Staff s: data.getRows()) {
            s.setPassword(null);
            staffList.add(s);
        }
//        但是改完了set的时候，要用setRecords()方法。因为说到底，我们是没有rows这个属性的。。。全靠偷records的。
//        所以如果给records赋值，getRows()就也能返回records的值。
        data.setRecords(staffList);
//        最后把data强转成IPage，虽然我不知道为啥要用IPage接收，甚至没有测试不强转对不对，但是强转对了，所以我就不管了。
//        有兴趣的可以不强转试试，反正我按照直觉强转了哈哈哈哈！
//        话说其实比我想象中的可能要添加个rows属性啊，可能要重写个IPage来继承啊来说，这个方法真的已经挺简便的了！
//        成功了真是可喜可贺！
        return Result.ok((IPage<Staff>)data);
    }

    @Override
    public Result update(int id, Staff staff) {
        if(staff.getId() == null) {
            staff.setId(id);
        }
        // TODO 啊这
//        如果有人用这个模拟发送个修改密码的请求，不就不会加密吗？（视频里都没提这个，直接就正常更新。。。）
//        String password = staff.getPassword();
//        if(password != null && StringUtils.isNotBlank(password)) {
//            staff.setPassword(new BCryptPasswordEncoder().encode(password));
//        }
//        还是说，我觉得好像删掉密码信息比较好，毕竟我看视频是打算在修改密码那里单独改密码，这里不准改！
        staff.setPassword(null);

        int i = baseMapper.updateById(staff);

        if(i < 1) {
            return Result.error("更新会员信息失败");
        }

        return Result.ok();
    }

    @Override
    public Result add(Staff staff) {
        if(staff == null || StringUtils.isBlank(staff.getUsername())) {
            return Result.error("用户名不能为空");
        }
        Staff s = getByUsername(staff.getUsername());
        if(s != null) {
            return Result.error("用户名已存在");
        }
        // TODO 啊这
        // 前端的新增员工也没传密码过来啊，你加密了个空气？？我还是设个默认的123456吧。。
        String password = new BCryptPasswordEncoder().encode("123456");// staff.getPassword());
        staff.setPassword(password);
        boolean b = this.save(staff);
        if(b) {
            return Result.ok();
        }
        return Result.error("新增员工信息失败");
    }

    @Override
    public Result checkPassword(PasswordREQ req) {
        if(req == null || StringUtils.isEmpty(req.getPassword())) {
            return Result.error("原密码不能为空");
        }
        Staff staff = baseMapper.selectById(req.getUserId());
        boolean b = new BCryptPasswordEncoder().matches(req.getPassword(), staff.getPassword());
        if(b) {
            return Result.ok();
        }
        return Result.error("原密码错误");
    }

    @Override
    public Result updatePassword(PasswordREQ req) {
        if(req == null || StringUtils.isEmpty(req.getPassword())) {
            return Result.error("新密码不能为空");
        }
        String password = new BCryptPasswordEncoder().encode(req.getPassword());

        Staff staff = baseMapper.selectById(req.getUserId());
        staff.setPassword(password);
        baseMapper.updateById(staff);
        return Result.ok();
    }

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public Result login(String username, String password) {

        Result error = Result.error("用户名或密码错误");

        if(StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            return error;
        }

        Staff staff = getByUsername(username);

        if(staff == null) {
            return error;
        }

        boolean b = new BCryptPasswordEncoder().matches(password, staff.getPassword());
        if(!b) {
            return error;
        }

        String token = jwtUtil.createJWT(staff.getId() + "", staff.getUsername(), true);
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        return Result.ok(map);
    }

    @Override
    public Result getUserInfo(String token) {
        Claims claims = jwtUtil.parseJWT(token);
        if(claims == null || StringUtils.isBlank(claims.getSubject())) {
            return Result.error("获取令牌失败");
        }
        String username = claims.getSubject();
        Staff staff = getByUsername(username);
        if(staff == null) {
            return Result.error("用户名不存在");
        }

        // TODO 啊这
//        你现在知道不能把密码返回到前端了？？你的查询员工方法已经全都泄露光了！
        staff.setPassword(null);

        return Result.ok(staff);
    }

    public Staff getByUsername(String username) {
        QueryWrapper<Staff> query = new QueryWrapper<>();
        query.eq("username", username);
        return baseMapper.selectOne(query);
    }

}
